/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package blms.services.internal;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import blms.domain.League;
import blms.domain.User;
import blms.exception.LeagueDoesNotExistException;
import blms.exception.RestrictionException;
import blms.exception.UserDoesNotExistException;
import blms.exception.ValidationException;
import blms.repository.LeagueRepository;
import blms.services.LeagueService;
import blms.services.UserService;
import blms.util.BLMSMessages;
import blms.util.ValidatorUtil;

/**
 * Default implementation of <code>LeagueService</code>
 * 
 * @author Jonhnny Weslley
 * @author Thiago Emmanuel Pereira da Cunha Silva, thiago.manel@gmail.com
 * @version 1.00, 22/04/2008
 * @since 1.0
 */
public class LeagueServiceImpl implements LeagueService {

	private final UserService userService;
	private final LeagueRepository leagues;

	/**
	 * @param userService
	 * @param leagues
	 */
	public LeagueServiceImpl(final UserService userService,
			final LeagueRepository leagues) {

		this.userService = userService;
		this.leagues = leagues;
	}

	/* (non-Javadoc)
	 * @see blms.services.LeagueService#createLeague(java.lang.String, java.lang.String, java.util.Date)
	 */
	public League createLeague(final String name, final String operator, final Date creationDate)
			throws UserDoesNotExistException, ValidationException, RestrictionException {
		if (ValidatorUtil.isBlankOrNull(operator)) {
			throw new ValidationException(BLMSMessages.REQUIRED_DATA_MESSAGE
					+ "league operator");
		}

		if (containsLeagueWithName(name)) {
			throw new RestrictionException(
					BLMSMessages.LEAGUE_ALREADY_EXISTS_MESSAGE);
		}

		final League league = new League(name, userService.getUser(operator), creationDate);
		league.validate();
		leagues.add(league);
		return league;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#contains(java.io.Serializable)
	 */
	public boolean contains(final Serializable id) {
		return leagues.contains(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#containsLeagueWithName(java.lang.String)
	 */
	public boolean containsLeagueWithName(final String name) {
		return leagues.containsLeagueName(name);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#getLeague(java.io.Serializable)
	 */
	public League getLeague(final Serializable id)
			throws LeagueDoesNotExistException {

		if (!contains(id)) {
			throw new LeagueDoesNotExistException(
					BLMSMessages.UNKNOWN_LEAGUE_MESSAGE);
		}
		return leagues.get(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#findLeagueByName(java.lang.String)
	 */
	public List<String> findLeagueByName(final String name)
			throws LeagueDoesNotExistException {
		return leagues.findLeagueByName(name);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#updateLeague(blms.domain.League,
	 *      blms.domain.League)
	 */
	public void updateLeague(final League league) throws ValidationException {
		league.validate();
		leagues.update(league);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#deleteLeague(java.io.Serializable)
	 */
	public void deleteLeague(final Serializable id)
			throws LeagueDoesNotExistException {
		final League league = getLeague(id);
		leagues.remove(league);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#removeAllLeagues()
	 */
	public void removeAllLeagues() {
		leagues.removeAll();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#join(blms.domain.League,
	 *      blms.domain.User, int)
	 */
	public void join(final League league, final User user,
			final int initialHandicap) throws ValidationException, RestrictionException {

		if (initialHandicap < 0) {
			throw new ValidationException(
					BLMSMessages.HANDICAP_CANT_BE_NEGATIVE_MESSAGE);
		}
		if (league.isMember(user)) {
			throw new RestrictionException(
					BLMSMessages.USER_IS_ALREADY_A_MEMBER_MESSAGE);
		}

		league.join(user).withHandicap(initialHandicap).on(new Date());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#leave(blms.domain.League,
	 *      blms.domain.User)
	 */
	public void leave(final League league, final User user)
			throws RestrictionException {

		if (!league.isMember(user)) {
			throw new RestrictionException(
					BLMSMessages.USER_IS_NOT_LEAGUE_MEMBER_MESSAGE);
		}
		if (league.getOperator().equals(user)) {
			throw new RestrictionException(
					BLMSMessages.OPERATOR_CAN_NOT_LEAVE_LEAGUE);
		}

		league.leave(user);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see blms.services.LeagueService#getPlayerLeagues(java.lang.String)
	 */
	public List<League> getPlayerLeagues(final Serializable playerId)
			throws UserDoesNotExistException {

		final User user = userService.getUser(playerId);

		final List<League> playerLeagues = new LinkedList<League>();

		for (final League league : leagues.getAll()) {

			if (league.isMember(user)) {
				playerLeagues.add(league);
			}
		}

		Collections.sort(playerLeagues, new Comparator<League>() {
			public int compare(final League o1, final League o2) {
				return o1.toString().compareTo(o2.toString());
			}
		});

		return playerLeagues;
	}
	
}